package com.hbwxz;

import com.hbwxz.utils.CommonUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 假设我们有一个电商项目，其中包含了商品库存管理和订单处理两个模块。商品库存管理模块负责更新商品库存数量，而订单处理模块负责处理用户提交的订单。
 * <p>
 * 在这个案例中，我们可以创建两个线程，分别模拟商品库存管理和订单处理两个模块的并发执行。
 *
 * @author shenzw
 * @date 2023/12/12
 */
public class ThreadStatusDemo {

    public static void main(String[] args) {

        // 在主线程中，我们创建并启动这两个线程，并演示线程状态的变化。
        // 创建商品库存管理线程
        InventoryManagementThread inventoryManagementThread = new InventoryManagementThread();

        // 创建订单处理线程
        OrderProcessingThread orderProcessingThread = new OrderProcessingThread();

        // 启动两个线程
        inventoryManagementThread.start();
        orderProcessingThread.start();

        // 模拟订单提交
        orderProcessingThread.submitOrder();

    }
}


/**
 * 首先，我们创建一个商品库存管理线程，使用 synchronized关键字保证在修改库存数量时的线程安全性。
 */
class InventoryManagementThread extends Thread {
    private int inventory = 100;

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 10; i++) { // 使用 synchronized关键字 锁定当前对象
                // 模拟商品库存的更新
                inventory--;
                CommonUtils.printThreadLog("商品库存数量 = " + inventory);

                try {
                    Thread.sleep(1000); // 线程休眠一秒钟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

/**
 * 然后，我们创建一个订单处理线程，使用 Lock 和 Condition 来控制线程的阻塞和唤醒。
 */
class OrderProcessingThread extends Thread {
    private final Lock lock = new ReentrantLock();

    private final Condition condition = lock.newCondition();

    private boolean orderSubmitted = false;

    @Override
    public void run() {
        lock.lock(); // 获取锁
        try {
            while (!orderSubmitted) { // 当订单未提交时，线程阻塞
                condition.await(); // 线程等待
            }

            // 订单已提交，开始处理订单
            CommonUtils.printThreadLog("处理订单中...");
            // 模拟订单处理过程
            TimeUnit.SECONDS.sleep(3000); // 模拟订单处理过程
            CommonUtils.printThreadLog("订单处理完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    /**
     * 提交订单的方法
     */
    public void submitOrder() {
        lock.lock();
        try {
            orderSubmitted = true; // 标志订单已提交
            condition.signal(); // 唤醒线程
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}